﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Yaml.Presentation.Parsing.TokenScanners {
    class MappingValueTokenScanner : BasicTokenScanner {
        public MappingValueTokenScanner(Scanner scanner)
            : base(scanner, ':') {
        }

        protected override bool CheckForToken() {
            // Values are either in flow or must be followed by a space or line break
            return base.CheckForToken() && (!Scanner.State.NotInFlow || Scanner.IsSpaceLineBreakOrNullChar(Reader.PeekRelative(1)));
        }

        protected override void BeforeScan() {
            base.BeforeScan();
            if (Scanner.State.SimpleKeys.IsKeyValid(Scanner.State.FlowDepth)) {
                // We have a simple to go here
                SimpleKey key = Scanner.State.SimpleKeys.RemoveSimpleKey(Scanner.State.FlowDepth);
                Scanner.Tokens.Insert(key.TokenNumber - Scanner.Tokens.TokensTaken, new Tokens.MappingKeyToken(key.Mark, key.Mark));
                // If this key starts a new block mapping, we need to add a new block mapping start
                if ( Scanner.State.NotInFlow ) {
                    if ( Scanner.State.Indentation.Push(key.Column)) {
                        Scanner.Tokens.Insert(key.TokenNumber - Scanner.Tokens.TokensTaken, new Tokens.BlockMappingStartToken(key.Mark, key.Mark, Scanner.State.Indentation.Current));
                    }
                }
                // There cannot be two simple keys one after the other
                Scanner.State.SimpleKeys.IsSimpleKeyAllowed = false;
            } else {
                // It must be a complex key
                if (Scanner.State.NotInFlow ) {
                    // We can create a complex key if and only if we can create a simple key
                    if ( !Scanner.State.SimpleKeys.IsSimpleKeyAllowed ) {
                        throw new ScannerException("mapping values are not allowed here");
                    }
                    if (Scanner.State.Indentation.Push(Scanner.State.Column)) {
                        Scanner.Tokens.Push(new Tokens.BlockMappingStartToken(Start, Start, Scanner.State.Indentation.Current)); 
                    }
                }
                // Simple keys are allowed after : only in the block context
                RemoveSimpleKey(Scanner.State.NotInFlow);
            }
        }

        protected override void AfterScan() {
            base.AfterScan();
        }

        protected override Yaml.Presentation.Tokens.Token CreateToken() {
            return new Tokens.MappingValueToken(Start, End);
        }
    }
}
